/**
 * 
 */
package com.lw.common.web.controller.base;

import java.util.Iterator;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import com.lw.common.basemodel.Json;
import com.lw.common.constant.LogConstant;
import com.lw.common.web.enums.ReturnStatusEnum;
import com.lw.common.web.exceptions.IllegalRequestException;
import com.lw.common.web.exceptions.NeedHighVersionException;
import com.lw.common.web.valid.ParamValidException;

/**
 * 
 * @Title: BasicController.java
 * @Package org.lanqiao.ssm.common.web.controller.base
 * @Description: (基础的控制类)
 * @author 刘伟 15818570028@163.com
 * @date 2016年10月2日 下午5:32:35
 * @version V1.0
 */
public class BasicController {
	protected final Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * 
	 * @Title: exceptionHandler
	 * @Description: (异常处理)
	 * @param @param
	 *            request
	 * @param @param
	 *            response
	 * @param @param
	 *            ex
	 * @param @return
	 * @param Exception
	 *            设定文件
	 * @return Json 返回类型
	 * 
	 */
	@ExceptionHandler(Exception.class)
	public Json exceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception ex)
			throws Exception {
		if (ex instanceof UnknownAccountException) {
			logger.info(LogConstant.LOG_MARK + ReturnStatusEnum.NO_ACCOUNT + ex.getMessage());
			return setFailed(ReturnStatusEnum.NO_ACCOUNT);
		} else if (ex instanceof IncorrectCredentialsException) {
			logger.info(LogConstant.LOG_MARK + ex.getMessage());
			return setFailed(ReturnStatusEnum.LOGIN_FAIL);
		} else if (ex instanceof LockedAccountException) {
			logger.info(LogConstant.LOG_MARK + ReturnStatusEnum.LOCKED_ACCOUNT.description() + ex.getMessage());
			return setFailed(ReturnStatusEnum.LOCKED_ACCOUNT);
		} else if (ex instanceof AuthenticationException) {
			logger.info(LogConstant.LOG_MARK + ReturnStatusEnum.AUTHENTICATION_ERROR);
			logger.info(LogConstant.LOG_MARK + ex.getMessage());
			return setFailed(ReturnStatusEnum.AUTHENTICATION_ERROR);
		} else if (ex instanceof MissingServletRequestParameterException) {
			logger.info(LogConstant.LOG_MARK + ex.getMessage());
			return setFailed(ReturnStatusEnum.OPERATOR_REQUESTPRARM_MISS, ex.getMessage());

		} else if (ex instanceof MethodArgumentTypeMismatchException) {
			logger.info(LogConstant.LOG_MARK + ex.getMessage());
			return setFailed(ReturnStatusEnum.OPERATOR_REQUESTPRARM_ERROR, ex.getMessage());
		} else if (ex instanceof BindException) {
			logger.info(LogConstant.LOG_MARK + ex.getMessage());
			return setFailed(ReturnStatusEnum.OPERATOR_REQUESTPRARM_ERROR, ex.getMessage());
		} else if (ex instanceof ConstraintViolationException) {
			ConstraintViolationException e = (ConstraintViolationException) ex;
			Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
			Iterator<ConstraintViolation<?>> it = constraintViolations.iterator();
			ConstraintViolation<?> c = it.next();
			return setFailed(ReturnStatusEnum.OPERATOR_REQUESTPRARM_ERROR, c.getMessageTemplate());
		} else if (ex instanceof ParamValidException) {
			ParamValidException e = (ParamValidException) ex;
			logger.info(LogConstant.LOG_MARK + e.getFieldErrors().get(0).getMessage());
			return setFailed(ReturnStatusEnum.OPERATOR_REQUESTPRARM_ERROR, e.getFieldErrors().get(0).getMessage());
		} else if (ex instanceof IllegalArgumentException) {
			logger.info(LogConstant.LOG_MARK + ex.getMessage());
			return setFailed(ReturnStatusEnum.OPERATOR_REQUESTPRARM_ILLEGAL_ARGUMENT, ex.getMessage());
		} else if (ex instanceof IllegalRequestException) {
			logger.info(LogConstant.LOG_MARK + ex.getMessage());
			return setFailed(ReturnStatusEnum.ILLEGAL_REQUEST);
		} else if (ex instanceof NeedHighVersionException) {
			logger.info(LogConstant.LOG_MARK + ex.getMessage());
			return setFailed(ReturnStatusEnum.NEED_HIGH_VERSION);
		} // 待定自定义异常
		logger.error(LogConstant.LOG_MARK, ex);
		return setFailed(ReturnStatusEnum.SERVER_INSIDE_FAIL);
	}

	/**
	 * 
	 * @Title: setSuccessModelMap
	 * @Description: (标准格式设置成功响应代码)
	 * @param @param
	 *            modelMap 需要返回的数据modelmap
	 * @param @return
	 *            设定文件
	 * @return ResponseEntity<ModelMap> 返回类型
	 * 
	 */
	protected ResponseEntity<ModelMap> setSuccessModelMap(ModelMap modelMap) {
		return setSuccessModelMap(modelMap, null);
	}

	/** 设置成功响应代码 */
	/**
	 * 
	 * @Title: setSuccessModelMap
	 * @Description: (标准格式设置成功响应代码)
	 * @param @param
	 *            modelMap 需要返回的数据modelmap
	 * @param @param
	 *            data 需要返回的数据集
	 * @param @return
	 *            设定文件
	 * @return ResponseEntity<ModelMap> 返回类型
	 * 
	 */
	protected ResponseEntity<ModelMap> setSuccessModelMap(ModelMap modelMap, Object data) {
		return setModelMap(modelMap, ReturnStatusEnum.SUCCESS, data, null);
	}

	/**
	 * 
	 * 
	 * @Description: (标准格式设置成功响应代码)
	 * @param @param
	 *            modelMap
	 * @param @param
	 *            code 代码
	 * @param @return
	 *            设定文件
	 * @return ResponseEntity<ModelMap> 返回类型
	 * 
	 */
	protected ResponseEntity<ModelMap> setModelMap(ModelMap modelMap, ReturnStatusEnum code) {
		return setModelMap(modelMap, code, null, null);
	}

	/**
	 * 
	 * @Title: setModelMap
	 * @Description: (这里用一句话描述这个方法的作用)
	 * @param @param
	 *            modelMap
	 * @param @param
	 *            code
	 * @param @param
	 *            data
	 * @param @param
	 *            msg
	 * @param @return
	 *            ResponseEntity<ModelMap>
	 * @return ResponseEntity<ModelMap> 返回类型
	 * 
	 */
	protected ResponseEntity<ModelMap> setModelMap(ModelMap modelMap, ReturnStatusEnum status, Object data,
			String msg) {
		if (data != null) {
			modelMap.put("data", data);
		} else {
			modelMap.put("data", "defult");
		}
		modelMap.put("statusCode", status.value());
		if (!StringUtils.isEmpty(msg)) {
			modelMap.put("msg", "1111");
		} else {
			modelMap.put("msg", status.description());
		}
		return ResponseEntity.ok(modelMap);
	}

	/**
	 * 
	 * @Title: setSimpleSuccess
	 * @Description: (简单设置成功)
	 * @param @return
	 * @return 返回类型 Json
	 * 
	 */
	protected Json setSimpleSuccess() {
		return setSimpleSuccess(null);
	}

	/**
	 * 
	 * @Title: setSimpleSuccess
	 * @Description: (简单设置成功)
	 * @param @param
	 *            succecss
	 * @param @return
	 * @return 返回类型 Json
	 * 
	 */
	protected Json setSimpleSuccess(boolean succecss) {
		return setSimpleSuccess(null);
	}

	/**
	 * 
	 * @Title: setSimpleSuccess
	 * @Description: (简单设置成功)
	 * @param @param
	 *            obj 需要返回的数据集
	 * @param @return
	 * @return 返回类型 Json
	 * 
	 */
	protected Json setSimpleSuccess(Object obj) {
		return setSimpleSuccess(ReturnStatusEnum.SUCCESS.description(), obj);
	}

	/**
	 * 
	 * @Title: setSimpleSuccess
	 * @Description: (快速设置失败)
	 * @param @param
	 *            msg 返回的提示信息
	 * @param @param
	 *            obj 返回的数据集
	 * @param @return
	 * @return 返回类型 Json
	 * 
	 */
	protected Json setSimpleSuccess(String msg, Object obj) {
		return new Json().setMsg(msg).setObj(obj).setSuccess(true).setStatusCode(ReturnStatusEnum.SUCCESS.value());
	}

	/**
	 * 
	 * @Title: setFailed
	 * @Description: (快速失败)
	 * @param @return
	 * @return 返回类型 Json
	 * 
	 */
	protected Json setFailed() {
		return setFailed(ReturnStatusEnum.OPERATOR_FAIL);
	}

	/**
	 * 
	 * @Title: setFailed
	 * @Description: (快速设置失败)
	 * @param @param
	 *            msg 失败的提示信息
	 * @param @return
	 * @return 返回类型 Json
	 * 
	 */
	protected Json setFailed(String msg) {
		return setFailed(ReturnStatusEnum.OPERATOR_FAIL, null, msg);
	}

	protected Json setFailed(ReturnStatusEnum status) {
		return setFailed(status, null);
	}

	/**
	 * 
	 * @Title: setFailed
	 * @Description: (快速设置失败)
	 * @param @param
	 *            msg 失败的提示信息
	 * @param @return
	 * @return 返回类型 Json
	 * 
	 */
	protected Json setFailed(ReturnStatusEnum status, Object obj) {
		return setFailed(status, obj, null);
	}

	/**
	 * 
	 * @Title: setFailed
	 * @Description: (快速设置失败)
	 * @param @param
	 *            msg 失败的提示信息
	 * @param @return
	 * @return 返回类型 Json
	 * 
	 */
	protected Json setFailed(ReturnStatusEnum status, Object obj, String msg) {
		Json json = new Json();
		if (status == null) {
			status = ReturnStatusEnum.SERVER_INSIDE_FAIL;
		}
		if (StringUtils.isEmpty(msg)) {
			json.setMsg(status.description());
		} else {
			json.setMsg(msg);
		}
		return json.setObj(obj).setStatusCode(status.value());
	}

}
